use crate::utils::templates;
use anyhow::Result;
use colored::*;
use std::fs;
use std::path::Path;

pub async fn run(
    name: String,
    template: String,
    typescript: bool,
    output_dir: String,
) -> Result<()> {
    println!("{} {} React project", "🚀 Creating".cyan().bold(), name);

    let project_dir = Path::new(&output_dir).join(&name);

    // 创建项目目录结构
    create_project_structure(&project_dir, &template, typescript).await?;

    // 生成配置文件
    generate_config_files(&project_dir, &name, &template, typescript).await?;

    // 生成源码文件
    generate_source_files(&project_dir, &template, typescript).await?;

    // 生成样式文件
    generate_style_files(&project_dir).await?;

    println!(
        "{} {} React project created successfully!",
        "✅".green(),
        name
    );
    println!("{} Next steps:", "📋".blue());
    println!("  cd {}", name);
    println!("  npm install");
    println!("  npm run dev");

    if template == "full" || template == "zustand" {
        println!("{} Features included:", "🎯".yellow());
        println!("  - React 18 with TypeScript/JavaScript");
        if template == "full" || template == "router" {
            println!("  - React Router for routing");
        }
        if template == "full" || template == "zustand" {
            println!("  - Zustand for state management");
        }
        println!("  - Tailwind CSS for styling");
        println!("  - ESLint for code quality");
    }

    Ok(())
}

async fn create_project_structure(
    project_dir: &Path,
    template: &str,
    typescript: bool,
) -> Result<()> {
    // 基础目录结构
    let dirs = ["src", "src/components", "src/assets", "src/utils", "public"];

    // 根据模板添加额外目录
    let mut extra_dirs = Vec::new();
    match template {
        "router" | "full" => {
            extra_dirs.push("src/pages");
        }
        _ => {}
    }

    if template == "zustand" || template == "full" {
        extra_dirs.push("src/stores");
    }

    if typescript {
        extra_dirs.push("src/types");
    }

    // 创建所有目录
    for dir in dirs.iter().chain(extra_dirs.iter()) {
        fs::create_dir_all(project_dir.join(dir))?;
    }

    println!("{} Project structure created", "📁".blue());
    Ok(())
}

async fn generate_config_files(
    project_dir: &Path,
    name: &str,
    template: &str,
    typescript: bool,
) -> Result<()> {
    // package.json
    let package_json = templates::react_package_json(name, template, typescript);
    fs::write(project_dir.join("package.json"), package_json)?;

    // vite.config.js/ts
    let vite_config = templates::react_vite_config(typescript);
    let config_ext = if typescript { "ts" } else { "js" };
    fs::write(
        project_dir.join(format!("vite.config.{}", config_ext)),
        vite_config,
    )?;

    // index.html
    let index_html = templates::react_index_html(name, typescript);
    fs::write(project_dir.join("index.html"), index_html)?;

    // TypeScript 配置
    if typescript {
        let tsconfig = templates::react_tsconfig_json();
        fs::write(project_dir.join("tsconfig.json"), tsconfig)?;

        let tsconfig_node = templates::react_tsconfig_node_json();
        fs::write(project_dir.join("tsconfig.node.json"), tsconfig_node)?;
    }

    // ESLint 配置
    let eslint_config = templates::react_eslint_config();
    fs::write(project_dir.join(".eslintrc.cjs"), eslint_config)?;

    // .gitignore
    let gitignore = templates::react_gitignore();
    fs::write(project_dir.join(".gitignore"), gitignore)?;

    // README.md
    let readme = templates::react_readme(name, template, typescript);
    fs::write(project_dir.join("README.md"), readme)?;

    println!("{} Configuration files generated", "⚙️".yellow());
    Ok(())
}

async fn generate_source_files(project_dir: &Path, template: &str, typescript: bool) -> Result<()> {
    let ext = if typescript { "tsx" } else { "jsx" };
    let js_ext = if typescript { "ts" } else { "js" };

    // main.tsx/jsx
    let main_content = templates::react_main_file(template, typescript);
    fs::write(project_dir.join(format!("src/main.{}", ext)), main_content)?;

    // App.tsx/jsx
    let app_content = templates::react_app_component(template, typescript);
    fs::write(project_dir.join(format!("src/App.{}", ext)), app_content)?;

    // 根据模板生成额外文件
    match template {
        "router" | "full" => {
            // 页面组件
            let home_page = templates::react_home_page(typescript);
            fs::write(
                project_dir.join(format!("src/pages/Home.{}", ext)),
                home_page,
            )?;

            let about_page = templates::react_about_page(typescript);
            fs::write(
                project_dir.join(format!("src/pages/About.{}", ext)),
                about_page,
            )?;
        }
        _ => {}
    }

    if template == "zustand" || template == "full" {
        // Zustand store
        let store_content = templates::react_zustand_store(typescript);
        fs::write(
            project_dir.join(format!("src/stores/counter.{}", js_ext)),
            store_content,
        )?;
    }

    if typescript {
        // 类型定义
        let types_content = r#"// 公共类型定义

export interface User {
  id: number
  name: string
  email: string
}

export interface ApiResponse<T = any> {
  code: number
  message: string
  data: T
}

export interface RouteParams {
  [key: string]: string | undefined
}
"#;
        fs::write(project_dir.join("src/types/index.ts"), types_content)?;
    }

    // 工具函数
    let utils_content = if typescript {
        r#"// 工具函数

/**
 * 格式化日期
 * @param date 日期对象
 * @param format 格式字符串
 * @returns 格式化后的日期字符串
 */
export function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  
  return format
    .replace('YYYY', String(year))
    .replace('MM', month)
    .replace('DD', day)
}

/**
 * 防抖函数
 * @param func 要防抖的函数
 * @param delay 延迟时间
 * @returns 防抖后的函数
 */
export function debounce<T extends (...args: any[]) => any>(
  func: T,
  delay: number
): (...args: Parameters<T>) => void {
  let timeoutId: NodeJS.Timeout
  return (...args: Parameters<T>) => {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => func(...args), delay)
  }
}

/**
 * 生成随机 ID
 * @param length ID 长度
 * @returns 随机字符串
 */
export function generateId(length: number = 8): string {
  return Math.random().toString(36).substring(2, 2 + length)
}
"#
    } else {
        r#"// 工具函数

/**
 * 格式化日期
 * @param {Date} date 日期对象
 * @param {string} format 格式字符串
 * @returns {string} 格式化后的日期字符串
 */
export function formatDate(date, format = 'YYYY-MM-DD') {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  
  return format
    .replace('YYYY', String(year))
    .replace('MM', month)
    .replace('DD', day)
}

/**
 * 防抖函数
 * @param {Function} func 要防抖的函数
 * @param {number} delay 延迟时间
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, delay) {
  let timeoutId
  return (...args) => {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => func(...args), delay)
  }
}

/**
 * 生成随机 ID
 * @param {number} length ID 长度
 * @returns {string} 随机字符串
 */
export function generateId(length = 8) {
  return Math.random().toString(36).substring(2, 2 + length)
}
"#
    };
    fs::write(
        project_dir.join(format!("src/utils/index.{}", js_ext)),
        utils_content,
    )?;

    // 创建简单的占位符文件
    let placeholder_file = "/* Placeholder for React logo */";
    fs::write(project_dir.join("src/assets/react.svg"), placeholder_file)?;

    let vite_placeholder = "/* Placeholder for Vite logo */";
    fs::write(project_dir.join("public/vite.svg"), vite_placeholder)?;

    println!("{} Source files generated", "📝".green());
    Ok(())
}

async fn generate_style_files(project_dir: &Path) -> Result<()> {
    // index.css
    let index_css = templates::react_index_css();
    fs::write(project_dir.join("src/index.css"), index_css)?;

    // App.css
    let app_css = templates::react_app_css();
    fs::write(project_dir.join("src/App.css"), app_css)?;

    println!("{} Style files generated", "🎨".magenta());
    Ok(())
}
